#!/usr/bin/python
# DNS-Snarf - Copyright (c) 2014, Nicholas Albright
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
import sys, socket, re, logging, os, signal, datetime
logging.getLogger("scapy.runtime").setLevel(logging.ERROR)
if len(sys.argv) < 3:
    print "Usage: %s [interface] [remote.syslog.server.ip|filename.log]" % sys.argv[0]
    sys.exit()
if os.geteuid() != 0:
    print "Root privs are required to sniff the interface. Please run with sudo."
    sys.exit()
def signal_handler(signal, frame):
        print "Break Signal recieved."
    sys.exit(0)
logtype = ""
if not re.search('[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+', sys.argv[2]):
    syslog = open(sys.argv[2], 'w', 1)
    logtype = "local"
else: 
    syslog = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    logtype = "remote"

def logger(data):
    timestamp = datetime.datetime.now().isoformat()
    if "local" in logtype: 
    	syslog.write(timestamp + data)
    if "remote" in logtype:
    	syslog.sendto(timestamp + data, (sys.argv[2],514))

def dnsrequest(pkt):
    if DNSRR in pkt and pkt[UDP].sport == 53:
    	client = pkt[IP].dst
    	clientport = pkt[UDP].dport
    	rip = pkt[DNSRR].rdata.strip('\'')
    	rname = pkt[DNSRR].rrname.strip('\'')
    	if pkt[DNSRR].type == 1: rtype = "A"
    	elif pkt[DNSRR].type == 2: rtype = "NS"
    	elif pkt[DNSRR].type == 5: rtype = "CNAME"
    	elif pkt[DNSRR].type == 6: rtype = "SOA"
    	elif pkt[DNSRR].type == 15: rtype = "MX"
    	elif pkt[DNSRR].type == 28: rtype = "AAAA"
    	else: rtype = pkt[DNSRR].type 
    	if pkt[DNSRR].rclass == 1: rclass = "IN"
    	else: rclass = pkt[DNSRR].rclass
    	rip = re.sub("[^a-z0-9:._-]", ".", rip)
    	logger(" [=] DNSSNARF: client: %s:%s query: %s %s %s (%s)\n" % (client, clientport, rname, rclass, rtype, rip))
from scapy.all import *
print "[+] Nicholas Albright's DNSSnarf\nStarting Capture on %s..." % sys.argv[1]
while True:
    try: sniff(iface=sys.argv[1], prn=dnsrequest, filter="udp and port 53", store=0)
    except: pass
